package com.hspedu.hspspringmvc.context;

import com.hspedu.hspspringmvc.annotation.AutoWired;
import com.hspedu.hspspringmvc.annotation.Controller;
import com.hspedu.hspspringmvc.annotation.Service;
import com.hspedu.hspspringmvc.handler.HspHandler;
import com.hspedu.hspspringmvc.xml.XMLPaser;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class HspWebApplicationContext {
    private ArrayList<String> classFullPathList = new ArrayList<>();

    public ConcurrentHashMap<String, Object> ioc = new ConcurrentHashMap<>();

    private String contextConfigLocation = "";

    public HspWebApplicationContext() {
    }

    public HspWebApplicationContext(String contextConfigLocation) {
        this.contextConfigLocation = contextConfigLocation;
    }

    public void init(){
        String basePackage = XMLPaser.getbasePackage(contextConfigLocation.split(":")[1]);
        String[] packges = basePackage.split(",");
        if (packges.length > 0){
            for (String packge : packges) {
                scanPackage(packge);
            }
        }
        executeInstance();
        executeAutoWired();
        System.out.println("classFullPathList" + classFullPathList);
        System.out.println("ioc" + ioc);
    }

    /**
     * 扫描指定包及其子包下的所有类文件，并将类全路径添加到列表中
     *
     * @param pack 需要扫描的包名（使用"."分隔的包路径）
     * @return 无返回值
     */
    public  void scanPackage(String pack){
        // 通过类加载器获取包对应的资源路径
        URL url = this.getClass()
                .getClassLoader()
                .getResource("/" + pack.replaceAll("\\.", "/"));
        String path = url.getPath();
        File file = new File(path);

        // 遍历包目录下的所有文件
        File[] files = file.listFiles();
        for (File f : files) {
            // 递归处理子目录
            if (f.isDirectory()) {
                scanPackage(pack + "." + f.getName());
            }
            // 处理.class文件并生成类全路径
            else {
                String classFullPath = pack + "." + f.getName().replace(".class", "");
                classFullPathList.add(classFullPath);
            }

        }

    }
    public void  executeInstance(){
        if (classFullPathList.size() == 0){
            return;
        }
        for (String classFullPath : classFullPathList) {
            try {
                Class<?> aClass = Class.forName(classFullPath);
                if (aClass.isAnnotationPresent(Controller.class)){
                String instanceName=    aClass.getSimpleName().substring(0,1).toLowerCase() +
                            aClass.getSimpleName().substring(1);
                    ioc.put(instanceName,aClass.newInstance());
                } else if (aClass.isAnnotationPresent(Service.class)) {
                    Service annotation = aClass.getAnnotation(Service.class);
                    String value = annotation.value();
                    if ("".equals(value)){
                        Class<?>[] interfaces = aClass.getInterfaces();
                        for (Class<?> anInterface : interfaces) {
                         String beanName =    anInterface.getSimpleName().substring(0,1).toLowerCase() +
                                    anInterface.getSimpleName().substring(1);
                            ioc.put(beanName,aClass.newInstance());
                        }
                    }else{
                        ioc.put(value,aClass.newInstance());
                    }


                }
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void executeAutoWired(){
        if (ioc.size() == 0){
            throw new RuntimeException("容器中, 没有可以装配的 bean");
        }
        for (Map.Entry<String, Object> entry : ioc.entrySet()) {
            Object bean = entry.getValue();
            String key = entry.getKey();
            Field[] declaredFields = bean.getClass().getDeclaredFields();
            for (Field declaredField : declaredFields) {
                if (declaredField.isAnnotationPresent(AutoWired.class)){
                    AutoWired annotation = declaredField.getAnnotation(AutoWired.class);
                    String beanName = annotation.value();
                    if ("".equals(beanName)){
                        Class<?> type = declaredField.getType();
                       beanName =  type.getSimpleName().substring(0,1).toLowerCase() +
                                type.getSimpleName().substring(1);
                    }
                    declaredField.setAccessible(true);
                    try {
                        if (ioc.get(beanName) == null) {
                            throw new RuntimeException("ioc 容器中, 没有可以注入的 bean");
                        }
                        declaredField.set(bean,ioc.get(beanName));
                    } catch (RuntimeException e) {
                        throw new RuntimeException(e);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }


                }
            }

        }
    }



}
